﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Linq;
using Hxsoft.AppV1;

namespace Hxsoft.AppV1.Module
{
	/// <summary>
	/// Dictionaries 类。
	/// </summary>
	public static partial class Dictionaries
	{
		public const string INFO_TYPE = "Dictionary";
		public const string DicCombineValueSeparator = ",";

		#region Helper
		/// <summary>
		/// 构建字典联合值字符串。
		/// </summary>
		/// <param name="values">原字典联合值字符串。</param>
		/// <returns>构建的字典联合值字符串。</returns>
		public static string BuildDicCombineValues(string values)
		{
			return Hxsoft.StringExtensions.Pack(values, DicCombineValueSeparator);
		}

		/// <summary>
		/// 构建字典联合值字符串。
		/// </summary>
		/// <param name="values">字典联合值集合。</param>
		/// <returns>构建的字典联合值字符串。</returns>
		public static string BuildDicCombineValues<T>(ICollection<T> values)
		{
			return BuildDicCombineValues(Hxsoft.StringExtensions.Compound(values, DicCombineValueSeparator));
		}

		/// <summary>
		/// 构建字典联合值字符串。
		/// </summary>
		/// <param name="value">进行构建的值。</param>
		/// <returns>构建的字典联合值字符串。</returns>
		public static string BuildDicCombineValues<T>(T value)
		{
			return BuildDicCombineValues(value.ToString());
		}

		/// <summary>
		/// 获取字典联合值字符串中的值列表字符串。
		/// </summary>
		/// <param name="cValues">字典联合值。</param>
		/// <returns>字典联合值字符串中的值列表字符串。</returns>
		public static string GetDicCombineValues(string cValues)
		{
			return Hxsoft.StringExtensions.Unpack(cValues, DicCombineValueSeparator);
		}

		/// <summary>
		/// 分解字典联合值标识。
		/// </summary>
		/// <param name="cValues">进行分解的字典联合值。</param>
		/// <returns>分解后的字典联合值标识集合。</returns>
		public static T[] DecompoundDicCombineValues<T>(string cValues)
		{
			return Hxsoft.StringExtensions.Decompound<T>(cValues, DicCombineValueSeparator, StringSplitOptions.RemoveEmptyEntries);
		}
		#endregion




		#region GetItems
		public static List<Dictionary> GetItems(this System.Data.Linq.Table<Dictionary> o, int classId, int? pDicId)
		{
			var q = from p in o
					where p.ClassId == classId
					select p;
			if (pDicId.HasValue)
				q = q.Where(p => p.PDicId == pDicId);
			else
				q = q.Where(p => p.PDicId == null);
			return q.ToList();
		}

		public static List<Dictionary> GetItems(this System.Data.Linq.Table<Dictionary> o, int classId)
		{
			var q = from p in o
					where p.ClassId == classId
					select p;
			
			return q.ToList();
		}


		public static List<Dictionary> GetItems(int classId, int? pDicId)
		{
			return GetItems(classId, pDicId, false);
		}

		public static List<Dictionary> GetItems(int classId)
		{
			return GetItems(classId, false);
		}

		public static List<Dictionary> GetItems(int classId, int? pDicId, bool trackObject)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = trackObject;

			return dc.Dictionaries.GetItems(classId, pDicId);
		}

		public static List<Dictionary> GetItems(int classId, bool trackObject)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = trackObject;

			return dc.Dictionaries.GetItems(classId);
		}




		public static List<Dictionary> GetItems(int? siteId, string classCode, int? pDicId)
		{
			return GetItems(siteId, classCode, pDicId, false);
		}

		public static List<Dictionary> GetItems(int? siteId, string classCode)
		{
			return GetItems(siteId, classCode,  false);
		}

		public static List<Dictionary> GetItems(int? siteId, string classCode, int? pDicId, bool trackObject)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = trackObject;

			int? classId = dc.DicClasses.GetIdentifier(siteId, classCode);
			if (!classId.HasValue)
				throw new ObjectNotExistsException(Res.ObjectNotExists);

			return GetItems(dc.Dictionaries, classId.Value, pDicId);
		}

		public static List<Dictionary> GetItems(int? siteId, string classCode, bool trackObject)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = trackObject;

			int? classId = dc.DicClasses.GetIdentifier(siteId, classCode);
			if (!classId.HasValue)
				throw new ObjectNotExistsException(Res.ObjectNotExists);

			return GetItems(dc.Dictionaries, classId.Value);
		}





		private static List<Dictionary> GetItemsByParentValue(GenericModuleDataContext dc, int classId, string pValue, bool trackObject)
		{
			int? pDicId = null;
			if (!string.IsNullOrEmpty(pValue))
			{
				pDicId = dc.Dictionaries.GetIdentifierByValue(classId, pValue);
				if (!pDicId.HasValue)
					throw new ObjectNotExistsException(Res.ObjectNotExists);
			}

			return GetItems(dc.Dictionaries, classId, pDicId);
		}

		public static List<Dictionary> GetItemsByParentValue(int classId, string pValue)
		{
			return GetItemsByParentValue(classId, pValue, false);
		}

		public static List<Dictionary> GetItemsByParentValue(int classId, string pValue, bool trackObject)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = trackObject;

			return GetItemsByParentValue(dc, classId, pValue, trackObject);
		}

		
		public static List<Dictionary> GetItemsByParentValue(int? siteId, string classCode, string pValue)
		{
			return GetItemsByParentValue(siteId, classCode, pValue, false);
		}
		
		public static List<Dictionary> GetItemsByParentValue(int? siteId, string classCode, string pValue, bool trackObject)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = trackObject;

			int? classId = dc.DicClasses.GetIdentifier(siteId, classCode);
			if (!classId.HasValue)
				throw new ObjectNotExistsException(Res.ObjectNotExists);

			return GetItemsByParentValue(dc, classId.Value, pValue, trackObject);
		}
		#endregion



		#region GetIdentifier

        /// <summary>
        /// 根据指定的信息获取字典标识。
        /// </summary>
        /// <param name="siteId"></param>
        /// <param name="classCode"></param>
        /// <param name="dicCode"></param>
        /// <returns></returns>
        public static int? GetIdentifier(int? siteId, string classCode, string dicCode)
        {
            GenericModuleDataContext dc = new GenericModuleDataContext();
            dc.ObjectTrackingEnabled = false;

            return dc.Dictionaries.GetIdentifier(siteId, classCode, dicCode);
        }

		/// <summary>
		/// 根据指定的信息获取字典标识。
		/// </summary>
		/// <param name="o">字典的集合。</param>
		/// <param name="siteId">所属站点标识。</param>
		/// <param name="classCode">类别代码。</param>
		/// <param name="dicCode">字典的代码。</param>
		/// <returns>指定的字典的标识。</returns>
		internal static int? GetIdentifier(this System.Data.Linq.Table<Dictionary> o, int? siteId, string classCode, string dicCode)
		{
			int? classId = (o.Context as GenericModuleDataContext).DicClasses.GetIdentifier(siteId, classCode);
			if (!classId.HasValue)
				throw new ObjectNotExistsException(Res.ObjectNotExists);

			return GetIdentifier(o, classId.Value, dicCode);
		}

		/// <summary>
		/// 根据指定的信息获取字典标识。
		/// </summary>
		/// <param name="o">字典的集合。</param>
		/// <param name="classId">所属类别标识。</param>
		/// <param name="dicCode">字典代码。</param>
		/// <returns>指定的字典的标识。</returns>
		internal static int? GetIdentifier(this System.Data.Linq.Table<Dictionary> o, int classId, string dicCode)
		{
			var q = from p in o
					where p.ClassId == classId && p.DicCode == dicCode
					select (int?)p.DicId;
			return q.SingleOrDefault();
		}

		/// <summary>
		/// 根据指定的信息获取字典标识。
		/// </summary>
		/// <param name="o">字典的集合。</param>
		/// <param name="classId">所属类别标识。</param>
		/// <param name="dicCode">字典代码。</param>
		/// <returns>指定的字典的标识。</returns>
		internal static int? GetIdentifierByValue(this System.Data.Linq.Table<Dictionary> o, int classId, string value)
		{
			var q = from p in o
					where p.ClassId == classId && p.Value == value
					select (int?)p.DicId;
			return q.FirstOrDefault();
		}

		/// <summary>
		/// 获取当前ID的最大值
		/// </summary>
		/// <param name="o"></param>
		/// <param name="classId"></param>
		/// <returns></returns>
        internal static int GetCurrentIdentifier(this System.Data.Linq.Table<Dictionary> o, int classId)
		{
            var exists = o.Any(p => p.ClassId == classId);
            if (!exists) return 1;
            return o.Where(p => p.ClassId == classId).OrderByDescending(p => p.DicId).FirstOrDefault().DicId + 1;            
		}

		/// <summary>
		/// 获取当前ID的最大值
		/// </summary>
		/// <param name="classId"></param>
		/// <returns></returns>
		public static int GetCurrentIdentifier(int classId)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;

            return dc.Dictionaries.GetCurrentIdentifier(classId);
		}

		#endregion



		#region GetItem
		/// <summary>
		/// 根据标识获取指定的字典项。
		/// </summary>
		/// <param name="classId">字典项所属的类别标识。</param>
		/// <param name="dicId">字典项的标识。</param>
		/// <returns>获取的字典项。</returns>
		public static Dictionary GetItem(int classId, int dicId)
		{
			return GetItem(classId, dicId, false);
		}

		/// <summary>
		/// 根据标识获取指定的字典项。
		/// </summary>
		/// <param name="classId">字典项所属的类别标识。</param>
		/// <param name="dicId">字典项的标识。</param>
		/// <param name="trackObject">是否跟踪对象。</param>
		/// <returns>获取的字典项。</returns>
		public static Dictionary GetItem(int classId, int dicId, bool trackObject)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = trackObject;

			return dc.Dictionaries.GetItem(classId, dicId);
		}

		/// <summary>
		/// 根据标识获取指定的字典项。
		/// </summary>
		/// <param name="o">字典项集合。</param>
		/// <param name="classId">字典项所属的类别标识。</param>
		/// <param name="dicId">字典项的标识。</param>
		/// <returns>获取的字典项。</returns>
		public static Dictionary GetItem(this System.Data.Linq.Table<Dictionary> o, int classId, int dicId)
		{
			return o.SingleOrDefault(p => p.ClassId == classId && p.DicId == dicId);
		}



		/// <summary>
		/// 根据标识获取指定的字典项。
		/// </summary>
		/// <param name="siteId">字典项所属的类别站点。</param>
		/// <param name="classCode">字典项所属的类别代码。</param>
		/// <param name="dicId">字典项的标识。</param>
		/// <returns>获取的字典项。</returns>
		public static Dictionary GetItem(int? siteId, string classCode, int dicId)
		{
			return GetItem(siteId, classCode, dicId, false);
		}

		/// <summary>
		/// 根据标识获取指定的字典项。
		/// </summary>
		/// <param name="siteId">字典项所属的类别站点。</param>
		/// <param name="classCode">字典项所属的类别代码。</param>
		/// <param name="dicId">字典项的标识。</param>
		/// <param name="trackObject">是否跟踪对象。</param>
		/// <returns>获取的字典项。</returns>
		public static Dictionary GetItem(int? siteId, string classCode, int dicId, bool trackObject)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = trackObject;

			return dc.Dictionaries.GetItem(siteId, classCode, dicId);
		}

		/// <summary>
		/// 根据标识获取指定的字典项。
		/// </summary>
		/// <param name="o">字典项集合。</param>
		/// <param name="siteId">字典项所属的类别站点。</param>
		/// <param name="classCode">字典项所属的类别代码。</param>
		/// <param name="dicId">字典项的标识。</param>
		/// <returns>获取的字典项。</returns>
		public static Dictionary GetItem(this System.Data.Linq.Table<Dictionary> o, int? siteId, string classCode, int dicId)
		{
			int? classId = DicClasses.GetIdentifier(siteId, classCode);
			if (classId == null) return null;
			return o.SingleOrDefault(p => p.ClassId == classId.Value && p.DicId == dicId);
		}




		/// <summary>
		/// 根据代码获取指定的字典项。
		/// </summary>
		/// <param name="classId">字典项所属的类别标识。</param>
		/// <param name="dicCode">获取的代码。</param>
		/// <returns>获取的字典项。</returns>
		public static Dictionary GetItem(int classId, string dicCode)
		{
			return GetItem(classId, dicCode, false);
		}
		
		/// <summary>
		/// 根据代码获取指定的字典项。
		/// </summary>
		/// <param name="classId">字典项所属的类别标识。</param>
		/// <param name="dicCode">获取的代码。</param>
		/// <param name="trackObject">是否跟踪对象。</param>
		/// <returns>获取的字典项。</returns>
		public static Dictionary GetItem(int classId, string dicCode, bool trackObject)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = trackObject;

			return dc.Dictionaries.GetItem(classId, dicCode);
		}
		
		/// <summary>
		/// 根据代码获取指定的字典项。
		/// </summary>
		/// <param name="o">字典项集合。</param>
		/// <param name="classId">字典项所属的类别标识。</param>
		/// <param name="dicCode">获取的代码。</param>
		/// <returns>获取的字典项。</returns>
		public static Dictionary GetItem(this System.Data.Linq.Table<Dictionary> o, int classId, string dicCode)
		{
			return o.SingleOrDefault(p => p.ClassId == classId && p.DicCode == dicCode);
		}




		/// <summary>
		/// 根据代码获取指定的字典项。
		/// </summary>
		/// <param name="classId">字典项所属的类别标识。</param>
		/// <param name="dicCode">获取的代码。</param>
		/// <returns>获取的字典项。</returns>
		public static Dictionary GetItemByValue(int classId, string value)
		{
			return GetItemByValue(classId, value);
		}
		
		/// <summary>
		/// 根据代码获取指定的字典项。
		/// </summary>
		/// <param name="classId">字典项所属的类别标识。</param>
		/// <param name="dicCode">获取的代码。</param>
		/// <param name="trackObject">是否跟踪对象。</param>
		/// <returns>获取的字典项。</returns>
		public static Dictionary GetItemByValue(int classId, string value, bool trackObject)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = trackObject;

			return dc.Dictionaries.GetItemByValue(classId, value);
		}
		
		/// <summary>
		/// 根据代码获取指定的字典项。
		/// </summary>
		/// <param name="o">字典项集合。</param>
		/// <param name="classId">字典项所属的类别标识。</param>
		/// <param name="dicCode">获取的代码。</param>
		/// <returns>获取的字典项。</returns>
		public static Dictionary GetItemByValue(this System.Data.Linq.Table<Dictionary> o, int classId, string value)
		{
			return o.FirstOrDefault(p => p.ClassId == classId && p.Value == value);
		}
		#endregion



		#region GetNameById
		public static string GetNameById(int? siteId, string classCode, int dicId)
		{
			int? classId = DicClasses.GetIdentifier(siteId, classCode);
			if (classId.HasValue)
				return GetNameById(classId.Value, dicId);
			return null;
		}

		public static string GetNameById(int classId, int dicId)
		{
			string key = classId + "-" + dicId;
			Dictionary<string, string> names = GenericCacheContainer.Instance.DicNameByIdDictionary;
			if (names.ContainsKey(key))
				return names[key];

			lock (names)
			{
				if (!names.ContainsKey(key))
				{
					GenericModuleDataContext dc = new GenericModuleDataContext();
					dc.ObjectTrackingEnabled = false;
					Dictionary dic = dc.Dictionaries.GetItem(classId, dicId);
					string value = dic == null ? "" : dic.Name;
					try
					{
						names[key] = value;
					}
					catch (IndexOutOfRangeException err)
					{
						names.Clear();
						names[key] = value;
					}
				}
			}
			return names[key];
		}

		public static string GetNameByCode(int? siteId, string classCode, string dicCode)
		{
			int? classId = DicClasses.GetIdentifier(siteId, classCode);
			if (classId.HasValue)
				return GetNameByCode(classId.Value, dicCode);
			return null;
		}

		public static string GetNameByCode(int classId, string dicCode)
		{
			string key = classId + "-" + dicCode;
			Dictionary<string, string> names = GenericCacheContainer.Instance.DicNameByIdDictionary;
			if (names.ContainsKey(key))
				return names[key];

			lock (names)
			{
				if (!names.ContainsKey(key))
				{
					GenericModuleDataContext dc = new GenericModuleDataContext();
					dc.ObjectTrackingEnabled = false;
					Dictionary dic = dc.Dictionaries.GetItem(classId, dicCode);
					string value = dic == null ? "" : dic.Name;
					try
					{
						names[key] = value;
					}
					catch (IndexOutOfRangeException err)
					{
						names.Clear();
						names[key] = value;
					}
				}
			}
			return names[key];
		}


		public static string[] GetNamesById(int? siteId, string classCode, int dicId, string dicRuleClassName)
		{
			int? classId = DicClasses.GetIdentifier(siteId, classCode);
			if (classId.HasValue)
				return GetNamesById(classId.Value, dicId, dicRuleClassName);
			return null;
		}
		
		public static string[] GetNamesById(int classId, int dicId, string dicRuleClassName)
		{
			long[] values = DictionaryRule.GetValues(dicRuleClassName, dicId);
			string[] strValues = new string[values.Length];
			for(int i = 0; i < values.Length; i++)
				strValues[i] = GetNameById(classId, (int)values[i]);
			return strValues;
		}
		#endregion



		#region GetValueById
		public static string GetValueById(int? siteId, string classCode, int dicId)
		{
			int? classId = DicClasses.GetIdentifier(siteId, classCode);
			if (classId.HasValue)
				return GetValueById(classId.Value, dicId);
			return null;
		}

		public static string GetValueById(int classId, int dicId)
		{
			string key = classId + "-" + dicId;
			Dictionary<string, string> values = GenericCacheContainer.Instance.DicValueByIdDictionary;
			if (values.ContainsKey(key))
				return values[key];

			lock (values)
			{
				if (!values.ContainsKey(key))
				{
					GenericModuleDataContext dc = new GenericModuleDataContext();
					dc.ObjectTrackingEnabled = false;
					Dictionary dic = dc.Dictionaries.GetItem(classId, dicId);
					string value = dic == null ? "" : dic.Value;
					try
					{
						values[key] = value;
					}
					catch (IndexOutOfRangeException err)
					{
						values.Clear();
						values[key] = value;
					}
				}
			}
			return values[key];
		}
		#endregion




		#region Exists
		/// <summary>
		/// 验证指定的字典项标识是否已经存在。
		/// </summary>
		/// <param name="o">字典项集合。</param>
		/// <param name="classId">字典项所属的类别标识。</param>
		/// <param name="dicId">验证的字典项标识。</param>
		/// <returns>布尔值表示指定的字典项标识是否已经存在。</returns>
		public static bool Exists(this System.Data.Linq.Table<Dictionary> o, int classId, int dicId)
		{
			return o.Any(p => p.ClassId == classId && p.DicId == dicId);
		}

		/// <summary>
		/// 验证指定的字典项代码是否已经存在。
		/// </summary>
		/// <param name="o">字典项集合。</param>
		/// <param name="classId">字典项所属的类别标识。</param>
		/// <param name="dicCode">验证的字典项代码。</param>
		/// <returns>布尔值表示指定的字典项代码是否已经存在。</returns>
		public static bool Exists(this System.Data.Linq.Table<Dictionary> o, int classId, string dicCode)
		{
			return o.Any(p => p.ClassId == classId && p.DicCode == dicCode);
		}
		/// <summary>
		///  验证指定的字典项代码是否已经存在。
		/// </summary>
		/// <param name="classId"></param>
		/// <param name="dicCode"></param>
		/// <returns></returns>
		public static bool Exists(int classId, string dicCode)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;
			return dc.Dictionaries.Exists(classId, dicCode);
		}
		#endregion
	}



	/// <summary>
	/// Dictionaries 类操作部分。
	/// </summary>
	public static partial class Dictionaries
	{
		#region Register
		internal static Dictionary Register(Dictionary registerDic)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();

			Dictionary dic = dc.Dictionaries.GetItem(registerDic.ClassId, registerDic.DicId);
			if (dic == null)
			{
				dic = registerDic.ToNewEntity<Dictionary>();
				if (dic.PDicId != null)
				{
					Dictionary pdic = dc.Dictionaries.GetItem(dic.ClassId, dic.PDicId.Value);
					if (pdic == null)
						throw new ObjectNotExistsException(Res.Dictionaries_NotExistsParent);
					pdic.ChildCount += 1;		// 上级节点的子节点数加1
				}
				dc.Dictionaries.InsertOnSubmit(dic);
				dc.SubmitChanges();
			}
			else
			{
				if (dic.DicCode != registerDic.DicCode || dic.Name != registerDic.Name || dic.Value != registerDic.Value)
				{
					// 修正数据，以确保数据的正确性
					dic.DicCode = registerDic.DicCode;
					dic.Name = registerDic.Name;
					dic.Value = registerDic.Value;

					try
					{
						dc.SubmitChanges(ConflictMode.ContinueOnConflict);
					}
					catch (ChangeConflictException e)
					{
						foreach (ObjectChangeConflict occ in dc.ChangeConflicts)
							occ.Resolve(RefreshMode.KeepCurrentValues);
					}
				}
			}

			// 返回只读数据。
			return registerDic.FillByEntity(dic);
		}
		#endregion




		#region Insert
		/// <summary>
		/// 添加字典项。
		/// </summary>
		/// <param name="insertedDic">添加的字典项。</param>
		/// <returns>添加的字典项。</returns>
		public static Dictionary Insert(Dictionary insertedDic)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();

			Dictionary dic = insertedDic.ToNewEntity<Dictionary>();
			dic.ChildCount = 0;

			GetInsertRight(dc, dic, true);	// 权限验证

			if (dc.Dictionaries.Exists(dic.ClassId, dic.DicId))
				throw new ObjectExistsException(Res.DicClasses_ExistsClassId);
			if (dc.Dictionaries.Exists(dic.ClassId, dic.DicCode))
				throw new ObjectExistsException(Res.DicClasses_ExistsClassCode);

			if (dic.PDicId != null)
			{
				Dictionary pdic = dc.Dictionaries.GetItem(dic.ClassId, dic.PDicId.Value);
				if (pdic == null)
					throw new ObjectNotExistsException(Res.Dictionaries_NotExistsParent);
				pdic.ChildCount += 1;		// 上级节点的子节点数加1
			}
			dc.Dictionaries.InsertOnSubmit(dic);
			dc.SubmitChanges();

			// 记录日志
			Logs.Insert(dc, null, null, INFO_TYPE, dic.DicId.ToString(), "Insert", dic.Name);

			// 返回只读数据
			return insertedDic.FillByEntity(dic);
		}
		#endregion



		#region Update
		private static readonly HashSet<string> _updatedColumns = typeof(Dictionary).GetEntityColumnNames(new string[] {
				"Name",
				"Value",
				"Indicators"
			}, true);				
		/// <summary>
		/// 修改字典项。
		/// </summary>
		/// <param name="updatedDic">修改的字典项。</param>
		/// <returns>修改的字典项。</returns>
		public static Dictionary Update(Dictionary updatedDic)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();

			Dictionary dic = dc.Dictionaries.GetItem(updatedDic.ClassId, updatedDic.DicId);
			if (dic == null)
				throw new ObjectNotExistsException(Res.Operation_ObjectNotExists);

			GetUpdateRight(dc, dic, true);	// 权限验证

			dic.FillByEntity(updatedDic, _updatedColumns);

			try
			{
				dc.SubmitChanges(ConflictMode.ContinueOnConflict);
			}
			catch (ChangeConflictException e)
			{
				foreach (ObjectChangeConflict occ in dc.ChangeConflicts)
				{
					occ.Resolve(RefreshMode.KeepCurrentValues);
				}
			}

			// 记录日志
			Logs.Insert(dc, null, null, INFO_TYPE, dic.DicId.ToString(), "Update", dic.Name);

			// 返回只读数据
			return updatedDic.FillByEntity(dic);
		}
		#endregion



		#region Delete
		/// <summary>
		/// 删除字典项。
		/// </summary>
		/// <param name="classId">字典项所属的类别标识。</param>
		/// <param name="dicId">删除的字典项标识。</param>
		public static void Delete(int classId, int dicId)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();

			Dictionary dic = dc.Dictionaries.GetItem(classId, dicId);
			if (dic == null)
				throw new ObjectNotExistsException(Res.Operation_ObjectNotExists);

			GetDeleteRight(dc, dic, true);	// 权限验证

			Delete(dc, dic);
			dc.SubmitChanges();

			// 记录日志
			Logs.Insert(dc, null, null, INFO_TYPE, dic.DicId.ToString(), "Delete", dic.Name);
		}

		#region internal Delete
		internal static void Delete(GenericModuleDataContext dc, Dictionary dic)
		{
			if (dic.Parent != null)
				dic.Parent.ChildCount -= 1;		// 上级节点数减1
			Dictionaries.DeleteByParent(dc, dic);	// 删除关联数据
			dc.Dictionaries.DeleteOnSubmit(dic);
		}

		internal static void DeleteByParent(GenericModuleDataContext dc, Dictionary parent)
		{
			IEnumerable<Dictionary> e = parent.Children.AsEnumerable();
			foreach (Dictionary i in e)
				Delete(dc, i);
		}

		internal static void DeleteByParent(GenericModuleDataContext dc, DicClass parent)
		{
			IEnumerable<Dictionary> e = parent.Dictionaries.AsEnumerable();
			foreach (Dictionary i in e)
				Delete(dc, i);
		}
		#endregion
		#endregion
	}



	/// <summary>
	/// Dictionaries 类对应操作权限部分。（受限站点资源。）
	/// </summary>
	public static partial class Dictionaries
	{
		#region GetInsertRight
		/// <summary>
		/// 获取当前用户是否有添加字典项的权限。
		/// </summary>
		/// <param name="dc">数据容器。</param>
		/// <param name="dic">添加的字典项对象。</param>
		/// <param name="triggerException">当未通过权限验证的时候是否引发异常。</param>
		/// <returns>布尔值表示当前用户是否有添加字典项的权限。</returns>
		public static bool GetInsertRight(GenericModuleDataContext dc, Dictionary dic, bool triggerException)
		{
			DicClass dicClass = dc.DicClasses.GetItem(dic.ClassId);
			return DicClasses.GetUpdateRight(dc, dicClass, triggerException);
		}

		/// <summary>
		/// 获取当前用户是否有添加字典项的权限。
		/// </summary>
		/// <param name="dic">添加的字典项对象。</param>
		/// <param name="triggerException">当未通过权限验证的时候是否引发异常。</param>
		/// <returns>布尔值表示当前用户是否有添加字典项的权限。</returns>
		public static bool GetInsertRight(Dictionary dic, bool triggerException)
		{
			return GetInsertRight(new GenericModuleDataContext(), dic, triggerException);
		}

		/// <summary>
		/// 获取当前用户是否有添加字典项的权限。
		/// </summary>
		/// <param name="dic">添加的字典项对象。</param>
		/// <returns>布尔值表示当前用户是否有添加字典项的权限。</returns>
		public static bool GetInsertRight(Dictionary dic)
		{
			return GetInsertRight(dic, false);
		}
		#endregion



		#region GetUpdateRight
		/// <summary>
		/// 获取当前用户是否有修改字典项的权限。
		/// </summary>
		/// <param name="dc">数据容器。</param>
		/// <param name="dic">修改的字典项对象。</param>
		/// <param name="triggerException">当未通过权限验证的时候是否引发异常。</param>
		/// <returns>布尔值表示当前用户是否有修改字典项的权限。</returns>
		public static bool GetUpdateRight(GenericModuleDataContext dc, Dictionary dic, bool triggerException)
		{
			DicClass dicClass = dc.DicClasses.GetItem(dic.ClassId);
			return DicClasses.GetUpdateRight(dc, dicClass, triggerException);
		}

		/// <summary>
		/// 获取当前用户是否有修改字典项的权限。
		/// </summary>
		/// <param name="dic">修改的字典项对象。</param>
		/// <param name="triggerException">当未通过权限验证的时候是否引发异常。</param>
		/// <returns>布尔值表示当前用户是否有修改字典项的权限。</returns>
		public static bool GetUpdateRight(Dictionary dic, bool triggerException)
		{
			return GetUpdateRight(new GenericModuleDataContext(), dic, triggerException);
		}

		/// <summary>
		/// 获取当前用户是否有修改字典项的权限。
		/// </summary>
		/// <param name="dic">修改的字典项对象。</param>
		/// <returns>布尔值表示当前用户是否有修改字典项的权限。</returns>
		public static bool GetUpdateRight(Dictionary dic)
		{
			return GetUpdateRight(dic, false);
		}
		#endregion



		#region GetDeleteRight
		/// <summary>
		/// 获取当前用户是否有删除字典项的权限。
		/// </summary>
		/// <param name="dc">数据容器。</param>
		/// <param name="dic">删除的字典项对象。</param>
		/// <param name="triggerException">当未通过权限验证的时候是否引发异常。</param>
		/// <returns>布尔值表示当前用户是否有删除字典项的权限。</returns>
		public static bool GetDeleteRight(GenericModuleDataContext dc, Dictionary dic, bool triggerException)
		{
			DicClass dicClass = dc.DicClasses.GetItem(dic.ClassId);
			return DicClasses.GetUpdateRight(dc, dicClass, triggerException);
		}

		/// <summary>
		/// 获取当前用户是否有删除字典项的权限。
		/// </summary>
		/// <param name="dic">删除的字典项对象。</param>
		/// <param name="triggerException">当未通过权限验证的时候是否引发异常。</param>
		/// <returns>布尔值表示当前用户是否有删除字典项的权限。</returns>
		public static bool GetDeleteRight(Dictionary dic, bool triggerException)
		{
			return GetDeleteRight(new GenericModuleDataContext(), dic, triggerException);
		}

		/// <summary>
		/// 获取当前用户是否有删除字典项的权限。
		/// </summary>
		/// <param name="dic">删除的字典项对象。</param>
		/// <returns>布尔值表示当前用户是否有删除字典项的权限。</returns>
		public static bool GetDeleteRight(Dictionary dic)
		{
			return GetDeleteRight(dic, false);
		}
		#endregion
	}



	/// <summary>
	/// Dictionaries 类后台管理部分。
	/// </summary>
	public static partial class Dictionaries
	{
		public static bool GetManageListRight(int classId)
		{
			return DicClasses.GetManageListRight();
		}


		public static bool GetManageListRight(int? siteId,int classId)
		{
			return DicClasses.GetManageListRight(siteId);
		}


		public static IQueryable<Dictionary> GetManageListQuery(GenericModuleDataContext dc, int classId, int? pDicId, string keyword)
		{
			var q = from p in dc.Dictionaries
					where p.ClassId == classId
					select p;

			if (pDicId.HasValue)
				q = q.Where(p => p.PDicId == pDicId.Value);
			else
				q = q.Where(p => p.PDicId == null);
			if (!string.IsNullOrEmpty(keyword))
				q = q.Where(p => p.Name.Contains(keyword));

			return q;
		}

		public static PaginationInfo<List<Dictionary>> GetPaginationManageList(int classId, int? pDicId, string keyword, int pageSize, int currentPage)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;

			IQueryable<Dictionary> q = GetManageListQuery(dc, classId, pDicId, keyword);

			PaginationInfo<List<Dictionary>> pageInfo = new PaginationInfo<List<Dictionary>>();
			pageInfo.PageSize = pageSize;
			pageInfo.CurrentPage = currentPage;
			pageInfo.RecordCount = q.Count();
			pageInfo.Records = q.Skip((currentPage - 1) * pageSize).Take(pageSize).ToList();
			return pageInfo;
		}


		public static List<Dictionary> GetBaseList(int classId, int? pDicId, string keyword, int? loadCount)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;

			IQueryable<Dictionary> q = GetManageListQuery(dc, classId, pDicId, keyword);

			if (loadCount.HasValue)
				return q.Take(loadCount.Value).ToList();
			return q.ToList();
		}
	}



	/// <summary>
	/// 字典值类别。
	/// </summary>
	public enum DicValueType
	{
		DicId,
		Value
	}

	public enum DicTextType
	{
		Name,
		Value
	}



	[Serializable]
	public struct DictionaryId
	{
		public int ClassId { get; set; }
		public int DicId { get; set; }
	}
}
